#include "StdAfx.h"
#include "PropHolder.h"
#include "uiToolKit.h"
#include "VarList.h"
#include "VarListVisitor.h"
CPropItemTrait gDefautItemTrait;
//////////////////////////////////////////////////////////////////////////

CPropHolder::CPropHolder(void):
m_pPropList(NULL),
m_pCurGroup(NULL),
m_bIsValid(false)
{
}

CPropHolder::~CPropHolder(void)
{
	if(m_pPropList)
	{
		m_pPropList->RemoveAll();
		m_pPropList->RedrawWindow();
	}

}

void CPropHolder::Initialize(CPropList* pPropList)
{
	m_pPropList = pPropList;
	m_bIsValid = AddItems();
	m_pPropList->RedrawWindow();
}

void CPropHolder::ResetGroup()
{
	m_pCurGroup = NULL;
}

bool CPropHolder::IsValid()
{
	return m_bIsValid && m_pPropList;
}
void CPropHolder::AddItem(CPropItem* pItem)
{
	if(m_pCurGroup)
	{
		m_pCurGroup->AddSubItem(pItem);
		m_pPropList->AddProperty(m_pCurGroup, FALSE,TRUE);
	}
	else
	{
		m_pPropList->AddProperty(pItem, FALSE,TRUE);
	}
}
void CPropHolder::AddGroup(const CString& szName, UINT nID/*=0*/)
{
	m_pCurGroup = new CPropItem(szName, nID);
	m_pPropList->AddProperty(m_pCurGroup, FALSE, TRUE);
}

BOOL CPropHolder::AddItem(const CString& name, double value, UINT nID, 
						const CPropItemTrait& trait, 
						const CString& description/* =_T("") */)
{
	_variant_t _value = value;
	CPropItem* pItem = new CPropItem(name, _value, description, nID);
	pItem->Enable(trait.bEnable);
	pItem->Enable(trait.bAllowEdit);
	
	AddItem(pItem);
	return true;
}

BOOL CPropHolder::AddItem(const CString& name, bool value, UINT nID, 
						const CPropItemTrait& trait, 
						const CString& description/* =_T("") */)
{
	_variant_t _value = (BOOL)value;
	CPropItem* pItem = new CPropItem(name, _value, description, nID);
	pItem->Enable(trait.bEnable);
	pItem->Enable(trait.bAllowEdit);
	
	AddItem(pItem);
	return true;
}

BOOL CPropHolder::AddItem(const CString& name, int value, UINT nID, 
						const CPropItemTrait& trait, 
						const CString& description/* =_T("") */)
{
	_variant_t _value = value;
	CPropItem* pItem = new CPropItem(name, _value, description, nID);
	pItem->Enable(trait.bEnable);
	pItem->Enable(trait.bAllowEdit);
	
	AddItem(pItem);
	return true;
}

BOOL CPropHolder::AddItem(const CString& name, const CString& value, UINT nID, 
						const CPropItemTrait& trait, 
						const CString& description/* =_T("") */)
{
	_variant_t _value = value;
	CPropItem* pItem = new CPropItem(name, _value, description, nID);
	pItem->Enable(trait.bEnable);
	pItem->Enable(trait.bAllowEdit);
	
	AddItem(pItem);
	return true;
}

BOOL CPropHolder:: AddItem(const CString& name, const CPointProxy& value, UINT nID,  
						 const CPropItemTrait& trait,
						 const CString& description/*=_T("")*/)
{
	CPropItem* pPointGroup = new CPropItem(name);

	_variant_t _valueX = double(value.X());
	CPropItem* pItemX = new CPropItem(_T("x"), _valueX, 
		description + _T(": x"), MAKEID_X(nID));
	pItemX->Enable(trait.bEnable);
	pItemX->Enable(trait.bAllowEdit);
	pPointGroup->AddSubItem(pItemX);

	_variant_t _valueY = double(value.Y());
	CPropItem* pItemY = new CPropItem(_T("y"), _valueY, 
		description+_T(": y"), MAKEID_Y(nID));
	pItemY->Enable(trait.bEnable);
	pItemY->Enable(trait.bAllowEdit);
	pPointGroup->AddSubItem(pItemY);

	_variant_t _valueZ = double(value.Z());
	CPropItem* pItemZ = new CPropItem(_T("z"), _valueZ, 
		description+_T(": z"), MAKEID_Z(nID));
	pItemZ->Enable(trait.bEnable);
	pItemZ->Enable(trait.bAllowEdit);
	pPointGroup->AddSubItem(pItemZ);

	AddItem(pPointGroup);

	return true;
}

bool CPropHolder::SetItemValue(UINT nID, const _variant_t& value)
{
	CPropItem* pItem = m_pPropList->FindItemByData(nID, TRUE);
	if(!pItem)
		return false;

	pItem->SetValue(value);
	return true;
}

bool CPropHolder::SetItemValue(UINT nID, const CPointProxy& value)
{
	CPropItem* pItem = m_pPropList->FindItemByData(MAKEID_X(nID), TRUE);
	if(!pItem)
		return false;
	pItem->SetValue(value.X());

	pItem = m_pPropList->FindItemByData(MAKEID_Y(nID), TRUE);
	if(!pItem)
		return false;
	pItem->SetValue(value.Y());

	pItem = m_pPropList->FindItemByData(MAKEID_Z(nID), TRUE);
	if(!pItem)
		return false;
	pItem->SetValue(value.Z());

	return true;
}
bool CPropHolder::GetItemValue(UINT nID, _variant_t& value)
{
	CPropItem* pItem = m_pPropList->FindItemByData(nID, TRUE);
	if(!pItem)
		return false;

	value = pItem->GetValue();
	return true;
}

class CPropItemVisitor : 
	public IVarListVisitor, 
	public IVarListUpdater
{
public:
	CPropItemVisitor(CPropHolder& refProp)
		:m_Prop(refProp)
	{
	}
	virtual void OnVisitItem(UINT idx, const _variant_t& value)
	{
		m_Prop.SetItemValue(idx, value);
	}

	virtual bool OnUpdateItem(UINT idx, _variant_t& value)
	{
		return m_Prop.GetItemValue(idx, value);
	}
private:
	CPropHolder& m_Prop;
};

bool CPropHolder::SetValues(const CVarList& varValues)
{
	if(!IsValid())
		return false;

	CPropItemVisitor visitor(*this);
	varValues.VisitItems(visitor);

	m_pPropList->RedrawWindow();
	return true;
}

bool CPropHolder::GetValues(CVarList& varValues)
{
	if(!IsValid())
		return false;

	CPropItemVisitor updater(*this);
	varValues.UpdateItems(updater);

	return true;
}
//////////////////////////////////////////////////////////////////////////
CPropItemTrait::CPropItemTrait()
:bEnable(TRUE),bAllowEdit(TRUE)
{

}

CPropItemTrait::~CPropItemTrait()
{

}

const CPropItemTrait& CPropItemTrait::Default()
{
	return gDefautItemTrait;
}
